#include "threadMovimiento.h"

threadMovimiento::threadMovimiento(juego* game) {
	this->game = game;
	//este valor viene del xml o dejarlo fijo asi
	altoPad= ALTO_ORIGINAL;
	anchoPad=20;
	sizebuffer=(2*sizeof(PosicionPad))+sizeof(PosicionTejo)+(2*sizeof(Puntaje))
			+sizeof(Bonus);
	quienSaca=true; // booleno para saber quien saca tejo.AL INICIO SACA EL JUGADOR 1
	ubicacionPad1.setX(40);
	ubicacionPad1.setY(300);
	ubicacionPad2.setX(950);
	ubicacionPad2.setY(300);
	memcpy(&(posPad1.puntoInicial), &ubicacionPad1, sizeof(ubicacionPad1));
	memcpy(&(posPad2.puntoInicial), &ubicacionPad2, sizeof(ubicacionPad2));
	TeclaEspacio = false;
	salida=false;
	
}

void threadMovimiento::run() {

	escenario* esc = this->game->getEscenario();

	SDL_Surface* screen = NULL;
	SDL_Surface* surface = NULL;
	listaFiguras* listaFig;

	listaFig = esc->getListaFiguras(esc->getCurrentLevel());
	//INSTANCIO PAD1 Y PAD2
	//DOS PUNTOS PARA UBICAR LOS 2 JUGADORES

	pad jugador1(ubicacionPad1, anchoPad, altoPad, surface);
	pad jugador2(ubicacionPad2, anchoPad, altoPad, surface);

	//como empieza sacando el jugador1 por default, este es el jugador activo
	jugadorActivo = &jugador1;
		
	setToDefault(jugador1,jugador2);

	//ESTA ES LA POSICION INICIAL DEL TEJO: sabiendo que saca jugador1
	PuntoTejoSaca1.setX(jugador1.getPInicial().getX() + jugador1.getAncho() +7);
	PuntoTejoSaca1.setY(jugador1.getPInicial().getY()+ jugador1.getAlto()/2);

	tejo tejo(PuntoTejoSaca1, radioTejo, surface);
	tejo.setRadio(radioTejo);

	posTejo.radio = tejo.getRadio();
	posTejo.puntoInicial.setX(tejo.getCentro().getX());
	posTejo.puntoInicial.setY(tejo.getCentro().getY());
	bonusActivo = NO_ACTIVO;

	Uint8 *tecla;

	tejo.setSpeed(0);


	colition.rectangulo_1();

	int vida=0;
	int nivel=0;
	int gol_player=0;
	int tejos=0;
	int tejosJugador1 = 0;
	int tejosJugador2 = 0;
	while ((tejos < 7) && !salida) {
		// Asigno Bonus Random //
		int asigno_bonus= esc->getRandom(1, 10000);
		switch (bonusActivo) {

			case NO_ACTIVO:
				if (asigno_bonus<100&&esc->Bonus_Type==0) {
					int Bonus_Codigo= esc->getRandom(1, 7);
					esc->setBonus(Bonus_Codigo);
					bonus.posicion = esc->Bonus_Posicion;
					bonus.esFinBonus = esc->Bonus_Type;
					std::cout<<"Bonus:"<<esc->Bonus_IdFig<<" Codigo:"<<esc->Bonus_Type;
					bonusActivo=ACTIVO;
					bonus.estado=ACTIVO;
				}
				break;
			case ACTIVO: 
				if (asigno_bonus<50) {
					esc->setBonus(0);
					bonus.esFinBonus = -1;
					bonusActivo=NO_ACTIVO;
					bonus.estado=NO_ACTIVO;
				}
				break;
			case EN_USO: 
				bonus.estado=EN_USO;
				break;
			case NONE:
				break;
			default:
				std::cout<<"NO DEBERIA ENTRAR AQUI"<<std::endl;
				break;
		}

		int movimiento1 = -1;
		int movimiento2 = -1;
		wait(MUTEX);
		if (game->getQueue1()->size() > 0) {
			movimiento1=game->getQueue1()->front();
			game->getQueue1()->pop_front();
		}
		if (game->getQueue2()->size() > 0) {
			movimiento2=game->getQueue2()->front();
			game->getQueue2()->pop_front();
		}
		release(MUTEX);
		bool seDesplazoPad = false;

		
		switch (movimiento1) {
			case ARRIBA:
				jugador1.desplazamientoArriba();
				jugador1.getPInicial();//MANDAR POR SOCKET
				PuntoTejoSaca1.setY(jugador1.getPInicial().getY() + 1+jugador1.getAlto()/2);
				PuntoTejoSaca1.setX(jugador1.getPInicial().getX()+tejo.getRadio()+20);//+20 cuando es fino
				seDesplazoPad = true;
				break;
			case ABAJO:
				jugador1.desplazamientoAbajo();
				jugador1.getPInicial();//MANDAR POR SOCKET
				PuntoTejoSaca1.setY(jugador1.getPInicial().getY() + 1+jugador1.getAlto()/2); //movimiento del tejo estatico con el jugador
				PuntoTejoSaca1.setX(jugador1.getPInicial().getX()+tejo.getRadio()+20);
				seDesplazoPad = true;

				break;
			case DISPARO:
				if (!TeclaEspacio && quienSaca) {
					tejo.setSpeed(velocidad);
					tejo.setAngle(2* PI);
					TeclaEspacio = true;
				}
				break;
		}

		switch (movimiento2) {
			case ARRIBA:
				jugador2.desplazamientoArriba();
				jugador2.getPInicial();//MANDAR POR SOCKET
				PuntoTejoSaca2.setY(jugador2.getPInicial().getY() + 1+jugador2.getAlto()/2);
				PuntoTejoSaca2.setX(jugador2.getPInicial().getX()+tejo.getRadio()+20);//+20
				seDesplazoPad = true;
				break;
			case ABAJO:
				jugador2.desplazamientoAbajo();
				jugador2.getPInicial();//MANDAR POR SOCKET
				PuntoTejoSaca2.setY(jugador2.getPInicial().getY() + 1+jugador2.getAlto()/2); //movimiento del tejo estatico con el jugador
				PuntoTejoSaca2.setX(jugador2.getPInicial().getX()+tejo.getRadio()+20); //-   +20
				seDesplazoPad = true;
				break;
			case DISPARO:
				if (!TeclaEspacio && !quienSaca) {
					tejo.setSpeed(velocidad);
					tejo.setAngle(1* PI);
					TeclaEspacio = true;
				}
				break;
		}

		bool perdioJugador1 = false;

		punto centroTejo;

		float deltaX = (tejo.getSpeed() + tejo.getRadio())
				* cos(tejo.getAngle());
		float deltaY = (tejo.getSpeed() + tejo.getRadio())
				* sin(tejo.getAngle());
		float puntoNuevoTejoY = tejo.getCentro().getY() - deltaY;
		float puntoNuevoTejoX = tejo.getCentro().getX() + deltaX;

		centroTejo.setY(puntoNuevoTejoY);
		centroTejo.setX(puntoNuevoTejoX);

		bool colisionTejoPad1 = false;
		bool colisionTejoPad2 = false;
		bool colisionTejoTriangulo = false;
		bool colisionTejoCirculo = false;
		bool colisionTejoRectangulo = false;

		colisionTejoPad1=colition.colisionTejoPad(&tejo, centroTejo, &jugador1); //aca vale choque tejo VS pad1 y pad2
		colisionTejoPad2=colition.colisionTejoPad(&tejo, centroTejo, &jugador2);

		if (colisionTejoPad1) {
			jugadorActivo = &jugador1;
			if (jugadorActivo->isPegajoso()) {
				tejo.setSpeed(0);
				quienSaca = true;
				TeclaEspacio = false;
			}	
		}

		if (colisionTejoPad2) {
			jugadorActivo = &jugador2;
			if (jugadorActivo->isPegajoso()) {
				tejo.setSpeed(0);
				quienSaca = false;
				TeclaEspacio = false;
			}
		}

		


		//PARA EL BONUS PEGAMENTO
		//si velocidad es cero entonces es un saque, entonces moverlo con junto al pad
		if (tejo.getSpeed() == 0.0f) {
			if (quienSaca) {
				tejo.getCentro().setX(PuntoTejoSaca1.getX());
				tejo.getCentro().setY(PuntoTejoSaca1.getY());
			} else {
				tejo.getCentro().setX(PuntoTejoSaca2.getX()-20-tejo.getRadio()*2);
				tejo.getCentro().setY(PuntoTejoSaca2.getY());
			}

		}

		int colisionTejoSegmento; // Para detectar el gol 1 si es con el arco p1, 2 arco p2

		int colisionTejoCirculo2;

		listaFiguras::iterator lf;
		for (lf=listaFig->begin(); lf!= listaFig->end(); ++lf) {
			if ((*lf)->esCirculo()) {
				char *Fig_ID;
				Fig_ID = new char[200];
				(*lf)->getIdFigura(Fig_ID);
				int colisionTejoCirculo=colisionTejoCirculo=colition.colisionCirculoTejo((circulo*)(*lf), &tejo);

				if (colisionTejoCirculo && bonusActivo==ACTIVO && (strcmp(
						Fig_ID, esc->Bonus_IdFig)==0)) {
					procesarBonus(*lf, Fig_ID, jugador1, jugador2, tejo);
					//bonusActivo=EN_USO;
				}
				delete [] Fig_ID;

			}

			if ((*lf)->esTriangulo()) {
				char *Fig_ID;
				Fig_ID = new char[200];
				(*lf)->getIdFigura(Fig_ID);
				int colisionTejoTriangulo=colition.colisionTrianguloTejo2((triangulo*)(*lf), &tejo);
				//ABAJO ESTA EL BONUS PARA EL TRIANGULO: FALTA QUIZAS ARREGLAR PERO ESA ES LA FORMA DE LLAMARLO
				if (colisionTejoTriangulo && bonusActivo==ACTIVO && (strcmp(Fig_ID, esc->Bonus_IdFig)==0)) {
					procesarBonus(*lf, Fig_ID, jugador1, jugador2, tejo);
					//bonusActivo=EN_USO;
				}
				delete [] Fig_ID;

			}


			if ((*lf)->esRectangulo()) {
				char *Fig_ID;
				Fig_ID = new char[200];
				(*lf)->getIdFigura(Fig_ID);
				colisionTejoRectangulo=colition.colisionTejoRectangulo(&tejo, centroTejo, (rectangulo*)(*lf));
				//int colisionTejoTriangulo=colition.colisionTrianguloTejo((triangulo*)(*lf), &tejo);
				//ABAJO ESTA EL BONUS PARA EL TRIANGULO: FALTA QUIZAS ARREGLAR PERO ESA ES LA FORMA DE LLAMARLO
				if (colisionTejoTriangulo && bonusActivo==ACTIVO && (strcmp(Fig_ID, esc->Bonus_IdFig)==0)) {
					procesarBonus(*lf, Fig_ID, jugador1, jugador2, tejo);
					//bonusActivo=EN_USO;
				}
				delete [] Fig_ID;

			}




		}

		//SUPONEMOS QUE GOL_PLAYER ES EL JUGADOR AL QUE LE HAN CONVERTIDO, NO DE QUIEN HA SIDO EL GOL

		gol_player = colition.esgol(&tejo);

		punto saca;

		if (gol_player == 1) {
			tejosJugador2++;
			jugadorActivo = &jugador1;
			logger::getInstancia()->log("JUGADOR ACTIVO: 1");
			tejos++;
			this->game->getJugador2()->getPuntaje()+=10;
			tejo.setSpeed(0);
			quienSaca=true;

			saca.setX(jugador1.getPInicial().getX()+tejo.getRadio()+20);
			saca.setY(jugador1.getPInicial().getY()+1+(jugador1.getAlto()/2));
	
			tejo.setCentro(saca);
			TeclaEspacio=false;
			tejo.desplazar_server();
			setToDefault(jugador1,jugador2);
			tejo.setRadio(radioTejo);
						
		} else if (gol_player ==2) {
			tejosJugador1++;
			jugadorActivo = &jugador2;
			tejos++;
			this->game->getJugador1()->getPuntaje()+=10;
			tejo.setSpeed(0);
			quienSaca=false;

			saca.setX(jugador2.getPInicial().getX()-tejo.getRadio());
			saca.setY(jugador2.getPInicial().getY()+1+(jugador2.getAlto()/2));

			tejo.setCentro(saca);
			TeclaEspacio=false;
			tejo.desplazar_server();
			setToDefault(jugador1,jugador2);
			tejo.setRadio(radioTejo);
		}

		posPad1.puntoInicial.setX(jugador1.getPInicial().getX());
		posPad1.puntoInicial.setY(jugador1.getPInicial().getY());
		posPad1.ancho = jugador1.getAncho();
		posPad1.alto = jugador1.getAlto();

		posPad2.puntoInicial.setX(jugador2.getPInicial().getX());
		posPad2.puntoInicial.setY(jugador2.getPInicial().getY());
		posPad2.ancho = jugador2.getAncho();
		posPad2.alto = jugador2.getAlto();

		posTejo.puntoInicial.setX(tejo.getCentro().getX());
		posTejo.puntoInicial.setY(tejo.getCentro().getY());
		posTejo.radio = tejo.getRadio();

		try {
			enviarActualizacion();
		} catch(IOException *ex) {
			delete ex;
			break;
		}


		tejo.desplazar_server();

		this->sleep(30);
	} // FIN DEL WHILE PRINCIPAL

	if (tejosJugador1 > tejosJugador2) {
		logger::getInstancia()->log("NIVEL GANADO POR JUGADOR 1");
		this->game->getJugador1()->getPuntaje()+=70;
	} else {
		logger::getInstancia()->log("NIVEL GANADO POR JUGADOR 2");
		this->game->getJugador2()->getPuntaje()+=70;
	}
}

void threadMovimiento::enviarActualizacion() {
	int code = GRAFICAR;
	Puntaje puntaje1, puntaje2;
	int size = (2*sizeof(PosicionPad))+sizeof(PosicionTejo)+(2*sizeof(Puntaje))
			+sizeof(Bonus);
	int totalSize = size +(2*(sizeof(int)));
	char* buffer = new char[totalSize];
	int posicionEscritura=0;

	puntaje1.valor = this->game->getJugador1()->getPuntaje();
	puntaje2.valor = this->game->getJugador2()->getPuntaje();
	memcpy(buffer + posicionEscritura, &code, sizeof(code));//CODEEEEE
	posicionEscritura+=sizeof(size);
	memcpy(buffer + posicionEscritura,&size,sizeof(size));
	posicionEscritura+=sizeof(size);

	memcpy(buffer + posicionEscritura,&posPad1,sizeof(posPad1));
	posicionEscritura+=sizeof(posPad1);
	memcpy(buffer + posicionEscritura,&posPad2,sizeof(posPad2));
	posicionEscritura+=sizeof(posPad1);

	memcpy(buffer + posicionEscritura,&posTejo,sizeof(posTejo));
	posicionEscritura+=sizeof(posTejo);

	memcpy(buffer + posicionEscritura,&puntaje1,sizeof(puntaje1));
	posicionEscritura+=sizeof(puntaje1);
	memcpy(buffer + posicionEscritura,&puntaje2,sizeof(puntaje1));
	posicionEscritura+=sizeof(puntaje1);

	memcpy(buffer + posicionEscritura,&bonus,sizeof(bonus));
	posicionEscritura+=sizeof(bonus);

	this->game->getServerOutputStream().write(reinterpret_cast<char*>(buffer),totalSize);
	
	delete[] buffer;
}

void threadMovimiento::procesarBonus(figura* fig, char* Fig_ID, pad& jugador1,pad& jugador2, tejo& Tejo) {

	if (this->game->getEscenario()->Bonus_Type==1) {
		if (jugadorActivo->getAlto() < altoPad+altoPad/3) {
			//bonus dimension +pad 
			jugadorActivo->setAlto(altoPad+altoPad/3);
		}
	}

	if (this->game->getEscenario()->Bonus_Type==2) {
		if (jugadorActivo->getAlto() > altoPad-altoPad/3) {
			//bonus dimension -pad 
			jugadorActivo->setAlto(altoPad-altoPad/3);
		}
	}

	if (this->game->getEscenario()->Bonus_Type==3) {
		if (Tejo.getRadio() < 5*radioTejo/3) {
			//bonus +tejo   (arreglarlo)
			Tejo.setRadio(radioTejo + radioTejo/3); //si cambio entonces cambio doble buffer a 14
		}
	}

	if (this->game->getEscenario()->Bonus_Type==4) {
		if (Tejo.getRadio() > radioTejo/3) {
			//bonus -tejo   
			Tejo.setRadio(radioTejo -radioTejo/3);
		}
	}

	if (this->game->getEscenario()->Bonus_Type==5) {
		if (Tejo.getSpeed() < (5*velocidad/3)) { 
			//bonus +velocidad
			Tejo.setSpeed(velocidad+ velocidad/3);
		}
	}

	if (this->game->getEscenario()->Bonus_Type==6) {
		if (Tejo.getSpeed() > (velocidad/3)) { 
			//bonus -velocidad
			Tejo.setSpeed(velocidad- velocidad/3);
		}
	}

	if (this->game->getEscenario()->Bonus_Type==7) {
		jugadorActivo->setPegajoso(true);
		if (jugadorActivo == &jugador1) {
			jugador2.setPegajoso(false);
		} else {
			jugador1.setPegajoso(false);
		}
		
	}

}

void threadMovimiento::setToDefault(pad& jugador1,pad& jugador2){
	radioTejo= (float)RADIO_ORIGINAL;
	velocidad=VELOCIDAD_ORIGINAL;
	huboPegamento=false;
	jugador1.setAlto(altoPad);
	jugador1.setAncho(anchoPad);
	jugador2.setAlto(altoPad);
	jugador2.setAncho(anchoPad);
	jugador1.setPegajoso(false);
	jugador2.setPegajoso(false);
	game->getEscenario()->Bonus_Type=0;
}
